home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 68K / Demo / stdwin / clock.py next >
Text File  |  1996-05-20  |  5KB  |  194 lines

  1. #! /usr/local/bin/python
  2.  
  3. # 'clock' -- A simple alarm clock
  4.  
  5. # The alarm can be set at 5 minute intervals on a 12 hour basis.
  6. # It is controlled with the mouse:
  7. # - Click and drag around the circle to set the alarm.
  8. # - Click far outside the circle to clear the alarm.
  9. # - Click near the center to set the alarm at the last time set.
  10. # The alarm time is indicated by a small triangle just outside the circle,
  11. # and also by a digital time at the bottom.
  12. # The indicators disappear when the alarm is not set.
  13. # When the alarm goes off, it beeps every minute for five minutes,
  14. # and the clock turns into inverse video.
  15. # Click or activate the window to turn the ringing off.
  16.  
  17. import stdwin
  18. from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \
  19.     WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE
  20. import mainloop
  21. import time
  22. from math import sin, cos, atan2, pi, sqrt
  23.  
  24. DEFWIDTH, DEFHEIGHT = 200, 200
  25.  
  26. MOUSE_EVENTS = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP)
  27. ORIGIN = 0, 0
  28. FARAWAY = 2000, 2000
  29. EVERYWHERE = ORIGIN, FARAWAY
  30.  
  31.  
  32. def main():
  33.     win = makewindow()
  34.     del win
  35.     mainloop.mainloop()
  36.  
  37. def makewindow():
  38.     stdwin.setdefwinsize(DEFWIDTH, DEFHEIGHT + stdwin.lineheight())
  39.     win = stdwin.open('clock')
  40.     setdimensions(win)
  41.     win.set = 1        # True when alarm is set
  42.     win.time = 11*60 + 40    # Time when alarm must go off
  43.     win.ring = 0        # True when alarm is ringing
  44.     win.dispatch = cdispatch
  45.     mainloop.register(win)
  46.     settimer(win)
  47.     return win
  48.  
  49. def cdispatch(event):
  50.     type, win, detail = event
  51.     if type == WE_DRAW:
  52.         drawproc(win, detail)
  53.     elif type == WE_TIMER:
  54.         settimer(win)
  55.         drawproc(win, EVERYWHERE)
  56.     elif type in MOUSE_EVENTS:
  57.         mouseclick(win, type, detail)
  58.     elif type == WE_ACTIVATE:
  59.         if win.ring:
  60.             # Turn the ringing off
  61.             win.ring = 0
  62.             win.begindrawing().invert(win.mainarea)
  63.     elif type == WE_SIZE:
  64.         win.change(EVERYWHERE)
  65.         setdimensions(win)
  66.     elif type == WE_CLOSE:
  67.         mainloop.unregister(win)
  68.         win.close()
  69.  
  70. def setdimensions(win):
  71.     width, height = win.getwinsize()
  72.     height = height - stdwin.lineheight()
  73.     if width < height: size = width
  74.     else: size = height
  75.     halfwidth = width/2
  76.     halfheight = height/2
  77.     win.center = halfwidth, halfheight
  78.     win.radius = size*45/100
  79.     win.width = width
  80.     win.height = height
  81.     win.corner = width, height
  82.     win.mainarea = ORIGIN, win.corner
  83.     win.lineheight = stdwin.lineheight()
  84.     win.farcorner = width, height + win.lineheight
  85.     win.statusarea = (0, height), win.farcorner
  86.     win.fullarea = ORIGIN, win.farcorner
  87.  
  88. def settimer(win):
  89.     now = time.time()
  90.     hours, minutes, seconds = win.times = calctime(now)
  91.     delay = 61 - seconds
  92.     win.settimer(10 * delay)
  93.     minutes = minutes + hours*60
  94.     if win.ring:
  95.         # Is it time to stop the alarm ringing?
  96.         since = (minutes - win.time + 720) % 720
  97.         if since >= 5:
  98.             # Stop it now
  99.             win.ring = 0
  100.         else:
  101.             # Ring again, once every minute
  102.             stdwin.fleep()
  103.     elif win.set and minutes == win.time:
  104.         # Start the alarm ringing
  105.         win.ring = 1
  106.         stdwin.fleep()
  107.  
  108. def drawproc(win, area):
  109.     hours, minutes, seconds = win.times
  110.     d = win.begindrawing()
  111.     d.cliprect(area)
  112.     d.erase(EVERYWHERE)
  113.     d.circle(win.center, win.radius)
  114.     d.line(win.center, calcpoint(win, hours*30 + minutes/2, 0.6))
  115.     d.line(win.center, calcpoint(win, minutes*6, 1.0))
  116.     str = "%02d:%02d" % (hours, minutes)
  117.     p = (win.width - d.textwidth(str))/2, win.height * 3 / 4
  118.     d.text(p, str)
  119.     if win.set:
  120.         drawalarm(win, d)
  121.         drawalarmtime(win, d)
  122.     if win.ring:
  123.         d.invert(win.mainarea)
  124.  
  125. def mouseclick(win, type, detail):
  126.     d = win.begindrawing()
  127.     if win.ring:
  128.         # First turn the ringing off
  129.         win.ring = 0
  130.         d.invert(win.mainarea)
  131.     h, v = detail[0]
  132.     ch, cv = win.center
  133.     x, y = h-ch, cv-v
  134.     dist = sqrt(x*x + y*y) / float(win.radius)
  135.     if dist > 1.2:
  136.         if win.set:
  137.             drawalarm(win, d)
  138.             erasealarmtime(win, d)
  139.             win.set = 0
  140.     elif dist < 0.8:
  141.         if not win.set:
  142.             win.set = 1
  143.             drawalarm(win, d)
  144.             drawalarmtime(win, d)
  145.     else:
  146.         # Convert to half-degrees (range 0..720)
  147.         alpha = atan2(y, x)
  148.         hdeg = alpha*360.0/pi
  149.         hdeg = 180.0 - hdeg
  150.         hdeg = (hdeg + 720.0) % 720.0
  151.         atime = 5*int(hdeg/5.0 + 0.5)
  152.         if atime <> win.time or not win.set:
  153.             if win.set:
  154.                 drawalarm(win, d)
  155.                 erasealarmtime(win, d)
  156.             win.set = 1
  157.             win.time = atime
  158.             drawalarm(win, d)
  159.             drawalarmtime(win, d)
  160.  
  161. def drawalarm(win, d):
  162.     p1 = calcpoint(win, float(win.time)/2.0, 1.02)
  163.     p2 = calcpoint(win, float(win.time)/2.0 - 4.0, 1.1)
  164.     p3 = calcpoint(win, float(win.time)/2.0 + 4.0, 1.1)
  165.     d.xorline(p1, p2)
  166.     d.xorline(p2, p3)
  167.     d.xorline(p3, p1)
  168.  
  169. def erasealarmtime(win, d):
  170.     d.erase(win.statusarea)
  171.  
  172. def drawalarmtime(win, d):
  173.     # win.time is in the range 0..720 with origin at 12 o'clock
  174.     # Convert to hours (0..12) and minutes (12*(0..60))
  175.     hh = win.time/60
  176.     mm = win.time%60
  177.     str = 'Alarm@%02d:%02d' % (hh, mm)
  178.     p1 = (win.width - d.textwidth(str))/2, win.height
  179.     d.text(p1, str)
  180.  
  181. def calcpoint(win, degrees, size):
  182.     alpha = pi/2.0 - float(degrees) * pi/180.0
  183.     x, y = cos(alpha), sin(alpha)
  184.     h, v = win.center
  185.     r = float(win.radius)
  186.     return h + int(x*size*r), v - int(y*size*r)
  187.  
  188. def calctime(now):
  189.     hours, minutes, seconds = time.localtime(now)[3:6]
  190.     hours = hours % 12
  191.     return hours, minutes, seconds
  192.  
  193. main()
  194.